package org.or5e.oss.core.api.bm;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;

import org.or5e.oss.core.BaseObject;
import org.or5e.oss.core.BaseUtility;
import org.or5e.oss.core.api.bm.BulkMailConfig.ATTRIB_KEY;
import org.or5e.oss.core.api.bm.server.SMTPServer;

public class BulkMailSPI extends BaseObject implements BulkMail {
	//private final static BulkMailContext context 			= new BulkMailContext();
	private HashMap<Double, CampaignThread> campaignList 	= new HashMap<Double, CampaignThread>();
	private Boolean initilized 								= Boolean.FALSE;

	private BulkMailConfig config 				= null;
	private BulkMailSecurityManager security 	= null;

	public BulkMailSPI() {
		Runtime.getRuntime().addShutdownHook(new MyShutdownHook());
		info("Bulk Mail Service Staring up.");
	}

	public boolean addServer(double sessionID, SMTPServer server)
			throws BulkMailException {
		checkNotInitilized();
		if(security == null) {
			throw new BulkMailException(BulkMailConstants.S001);
		}
		security.checkAddServer();
		
		CampaignThread campaign = getCampaign(sessionID);
		campaign.addServer(server);
		return false;
	}

	public boolean removeServer(double sessionID, SMTPServer server) throws BulkMailException {
		checkNotInitilized();
		CampaignThread campaign = getCampaign(sessionID);
		campaign.removeServer(server);
		return false;
	}

	public ArrayList<SMTPServer> getServerList(double sessionID)
			throws BulkMailException {
		checkNotInitilized();

		CampaignThread campaign = getCampaign(sessionID);
		return campaign.getServerList();
	}

	public BulkMailStatus getStatus(double sessionID) throws BulkMailException {
		checkNotInitilized();
		return null;
	}

	public void init(BulkMailConfig config) throws BulkMailException {
		checkInitilized();
		setSecurityManager(new BulkMailSecurityManager());
		security.checkInit();
		

		try {
			String[] fileNames = BaseUtility.getUtility().validateEmail(config);
			info("Validate Email is Done.");

			config.setAttribute(ATTRIB_KEY.GOODFILE, new File(fileNames[0]));
			config.setAttribute(ATTRIB_KEY.BADFILE, new File(fileNames[1]));

			this.initilized = true;
			this.config = config;
			info("Initilization of Service is done.");
		}
		catch (FileNotFoundException e) {
			debug("Initilzation Failed....");
			error(e.getMessage());
		}
		catch (IOException e) {
			debug("Initilzation Failed....");
			error(e.getMessage());
		}
	}

	public void pauseCampaign(double sessionID) throws BulkMailException {
		checkNotInitilized();
		// Not Been Planned for First Iteration
	}

	public void resumeCampaign(double sessionID) throws BulkMailException {
		checkNotInitilized();
		// Not Been Planned for First Iteration
	}

	public void setLogger(OutputStream outStream) throws BulkMailException {
		checkNotInitilized();
		// Not Been Planned for First Iteration
	}

	public double startCampaign(String campaignName) throws BulkMailException {
		checkNotInitilized();
		CampaignThread campaign = new CampaignThread(campaignName, this.config, this);
		Double sessionID = new Double(Math.random());
		campaignList.put(sessionID, campaign);
		campaign.start();
		return sessionID;
	}

	public void stopCampaign(double sessionID) throws BulkMailException {
		checkNotInitilized();
		CampaignThread campaign = getCampaign(sessionID);
		campaign.stopThread();
	}
	public void setSecurityManager(BulkMailSecurityManager security) {
		this.security = security;
	}

	@Override
	public String getName() {
		return "BulkMailSPI";
	}
	
	private void checkInitilized() throws BulkMailException {
		if(initilized) {
			throw new BulkMailException(BulkMailConstants.E002);
		}
	}
	private void checkNotInitilized() throws BulkMailException {
		if(security == null){
			throw new BulkMailException(BulkMailConstants.S001);
		}
		if(!initilized) {
			throw new BulkMailException(BulkMailConstants.E001);
		}
	}
	private CampaignThread getCampaign(Double sessionID) {
		return campaignList.get(sessionID);
	}
	public void shutdown(){
		Set<Double> sessions = campaignList.keySet();
		for(Double session: sessions) {
			CampaignThread campaign = getCampaign(session);
			campaign.stopThread();
			info("Campaign "+campaign.campaignName+" is Stopped");
		}
		info("Bulk Mail Service Shutting Down.");
	}

	private class MyShutdownHook extends Thread {
        public void run() {
            shutdown();
        }
    }
}